package gl.java.umsp.websocket;

import com.sun.jndi.toolkit.url.Uri;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import lombok.extern.slf4j.Slf4j;

import java.io.FileNotFoundException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class HttpRequestHandler extends
        SimpleChannelInboundHandler<FullHttpRequest> { // 1
    //应该用树作为数据结构来保存路径,方便匹配
    private static Map<String, IHttpController> routeMap = new HashMap();

    static {
        HttpRequestHandler.addRoute("/script", new RouteScript());
        HttpRequestHandler.addRoute("/", new RouteIndex());
        HttpRequestHandler.addRoute("/ws", new RouteWebSocket());
    }


    public static void addRoute(String uri, IHttpController controller) {
        log.info("addRoute: " + uri + " => " + controller.getClass());
        routeMap.put(uri, controller);
    }

    public HttpRequestHandler() {
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
        log.info("request.uri: " + request.getUri());
        URI uri = URI.create(request.getUri());
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(
                request.getProtocolVersion(), HttpResponseStatus.OK);
        try {
            response.headers().set(HttpHeaders.Names.CONTENT_TYPE,
                    "text/html; charset=UTF-8");
            boolean isMatch = false;
            if ((uri.getPath().equals("/") || uri.getPath().equals("/index"))) {
                if (HttpRequestHandler.routeMap.get("/").onHttpRequest(request, response, ctx)) {
                    isMatch = true;
                }
            } else {
                for (String s : HttpRequestHandler.routeMap.keySet()) {
                    //精确匹配路径路由器
                    if (uri.getPath().equals(s)) {
                        if (HttpRequestHandler.routeMap.get(s).onHttpRequest(request, response, ctx)) {
                            isMatch = true;
                            break;
                        }
                    }
                }
//                if (!isMatch) {
//                    //根路径匹配路由
//                    String[] split = uri.getPath().split("/");
//                    for (String s : HttpRequestHandler.routeMap.keySet()) {
//                        if (split != null && split.length > 2 && uri.getPath().startsWith(s)) {
//                            if (HttpRequestHandler.routeMap.get(s).onHttpRequest(request, response, ctx)) {
//                                ctx.writeAndFlush(response);
//                                isMatch = true;
//                            }
//                        }
//                    }
//                }

            }

            if (!isMatch) {
                //try load the static res
                try {
                    new RouteStaticResource(request.getUri()).onHttpRequest(request, response, ctx);
                    isMatch = true;
                } catch (FileNotFoundException e) {
                    log.info(e.toString());
                } catch (Exception e) {
                    throw e;
                }
            }
            if (!isMatch) {
                log.info("404:" + request.getUri());
                RouteBase.return404(request, response, ctx);
            }
        } catch (Exception e) {
            log.error(e.toString());
            RouteBase.return500(request, response, ctx, e);
        }

    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        Channel incoming = ctx.channel();
        log.warn("Client:" + incoming.remoteAddress() + "异常");
        cause.printStackTrace();
        ctx.close();
    }

    public static void main(String[] args) {
        String url = "/public/manuals/appliances?id=1&name=jankin#ge";
        URI uri = URI.create(url);
        log.info("uri.getPath()" + uri.getPath());
        log.info("" + uri.getPath().startsWith("/public"));
        log.info("uri.getPath()" + uri.getQuery());
    }
}